﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web.Compilation;

namespace OrchardFork.Framework
{
    public class TypeUtil
    {
        public static IEnumerable<Type> FilterTypesInAssemblies(Predicate<Type> predicateType, Predicate<Assembly> predicateAssembly)
        {
            // Go through all assemblies referenced by the application and search for types matching a predicate
            IEnumerable<Type> typesSoFar = Type.EmptyTypes;

            var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToList().Where(assembly => predicateAssembly(assembly));

            foreach (var assembly in assemblies)
            {
                Type[] typesInAsm;
                try
                {
                    typesInAsm = assembly.GetTypes();
                }
                catch (ReflectionTypeLoadException ex)
                {
                    typesInAsm = ex.Types;
                }
                typesSoFar = typesSoFar.Concat(typesInAsm);
            }
            return typesSoFar.Where(type => TypeIsPublicClass(type) && predicateType(type));
        }

        public static bool TypeIsPublicClass(Type type)
        {
            return (type != null && type.IsPublic && type.IsClass && !type.IsAbstract);
        }
    }
}
